/**
 * \file ktypes.h
 * \brief Common macros and kernel types.
 * \author Corey Tabaka
 */

/*
   Copyright 2005 Corey Tabaka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#ifndef __USER_TYPES_H__
#define __USER_TYPES_H__

#include <stdlib.h>

#ifdef __GNUC__

#define __data __attribute__ ((__section__ (".data")))

#if defined(__cplusplus)
#define offsetof(type, field)						\
	(__offsetof__ (reinterpret_cast <size_t>		\
	(&reinterpret_cast <char &>						\
	(static_cast<type *> (0)->field))))
#else
 #define	offsetof(type, field)	((size_t)(&((type *)0)->field))
#endif
#ifndef rangeof
 #define	rangeof(type, start, end)				\
 	(__offsetof(type, end) - __offsetof(type, start))
#endif

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:        the pointer to the member.
 * @type:       the type of the container struct this is embedded in.
 * @member:     the name of the member within the struct.
 *
 */
#ifndef container_of
#define container_of(ptr, type, member) ({					\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type, member) ); })
#endif

	// FIXME: configure
#	ifndef __ppc__
#		define FASTCALL __attribute__((regparm (3)))
#	else
#		define FASTCALL
#	endif

#	define FUNCTION_CONST	__attribute__((const))
#	define PACKED		__attribute__((packed))
#	define UNUSED		__attribute__((unused))
#	define DEPRECATED	__attribute__((deprecated))
#	define NORETURN		__attribute__((noreturn))
#	define ALIGN_STRUCT(n)	__attribute__((aligned(n)))
#else
#	error "you're not using the GNU C compiler :-( please add the macros and conditionals for your compiler"
#endif /* !__GNUC__ */

/** unsigned 8-bit integer */
typedef unsigned char		uint8;
/** unsigned 16-bit integer */
typedef unsigned short		uint16;
/** unsigned 32-bit integer */
typedef unsigned int		uint32;
/** unsigned 64-bit integer */
typedef unsigned long long	uint64;

/** signed 8-bit integer */
typedef signed char			sint8;
/** singed 16-bit integer */
typedef signed short		sint16;
/** signed 32-bit integer */
typedef signed int			sint32;
/** singed 64-bit integer */
typedef signed long long	sint64;

/** unsigned machine width integer */
typedef unsigned int		uint;
/** signed machine width integer */
typedef signed int			sint;

/** unsigned byte width integer */
typedef unsigned char		byte;

#ifndef UINT128
#define UINT128

/**
 * \brief Struct for composing unsigned 128-bit integers
 */
typedef struct uint128 {
	uint64 l;
	uint64 h;
} uint128;
typedef struct sint128 {
	sint64 l;
	sint64 h;
} sint128;

#endif

/**
 * \brief Struct for operating on 64-bit timestamp values
 */
typedef union {
	struct {
		uint32 low;
		uint32 high;
	};
	uint64 value;
} timestamp_t;

/**
 * \brief Maximum machine width unsigned integer
 */
//#define UINT_MAX 0xffffffffU

/**
 * \brief Process ID
 */
typedef uint32 pid_t;

/**
 * \brief Thread ID
 */
typedef uint32 tid_t;

/**
 * \brief User ID
 */
typedef uint32 uid_t;

/**
 * \brief Group ID
 */
typedef uint32 gid_t;

/**
 * \brief Message Queue ID
 */
typedef uint32 qid_t;

/**
 * \brief Process entry point function type
 */
typedef void (*ProcessEntryPoint)(void);

/**
 * \brief Task entry point function type
 */
typedef void (*TaskEntryPoint)(void *);

/**
 * \brief x86 TSS structure
 */
typedef struct {
	uint16	backlink, __blh;
	uint32	esp0;
	uint16	ss0, __ss0h;
	uint32	esp1;
	uint16	ss1, __ss1h;
	uint32	esp2;
	uint16	ss2, __ss2h;
	uint32	cr3;
	uint32	eip;
	uint32	eflags;
	uint32	eax, ecx, edx, ebx;
	uint32	esp, ebp, esi, edi;
	uint16	es, __esh;
	uint16	cs, __csh;
	uint16	ss, __ssh;
	uint16	ds, __dsh;
	uint16	fs, __fsh;
	uint16	gs, __gsh;
	uint16	ldt, __ldth;
	uint16	trace, bitmap;
	
	uint8 tss_bitmap[8192];
} __attribute__ ((packed)) tss_t;

/**
 * \brief x86 stack register image.
 *
 * The layout of this structure must match the order of registers
 * pushed and popped by the exception handlers in pm_system.asm
 */
typedef struct
{
	uint32 task_esp;
	uint32 edi, esi, ebp, esp, ebx, edx, ecx, eax;	// pushed by common handler (PUSHA)
	uint32 ds, es, fs, gs;							// pushed by common handler
	uint32 which_int;								// pushed by stub
	uint32 err_code;								// pushed by interrupt or stub
	// pushed by exception. Exception may also push err_code.
	// user_esp and user_ss are pushed only if a privilege change occurs.
	uint32 eip, cs, eflags, user_esp, user_ss;
} __attribute__ ((packed)) regs_t;

/**
 * \brief x86 stack register image plus vm86 mode registers.
 *
 * This is an extension of the regs_t structure for vm86 register images.
 */
typedef struct
{
	uint32 task_esp;
	uint32 edi, esi, ebp, esp, ebx, edx, ecx, eax;	// pushed by common handler (PUSHA)
	uint32 ds, es, fs, gs;							// pushed by common handler
	uint32 which_int;								// pushed by stub
	uint32 err_code;								// pushed by interrupt or stub
	// pushed by exception. Exception may also push err_code.
	uint32 eip, cs, eflags, vm_esp, vm_ss, vm_es, vm_ds, vm_fs, vm_gs;
} __attribute__ ((packed)) regs_vm86_t;

#endif
